# -*- coding: utf-8 -*-
import frappe
from frappe.model.document import Document
from frappe.utils import today, cstr, flt
import json

class ScrapMaterial(Document):
    """
    余料控制器类
    管理余料的基本信息、状态变更和业务逻辑
    """
    
    def validate(self):
        """验证数据有效性"""
        self.validate_unique_scrap_id()
        self.validate_warehouse_location()
        self.validate_dimensions()
        self.validate_quantity()
    
    def before_save(self):
        """保存前处理"""
        self.set_creation_date()
        self.generate_qr_code()
    
    def on_update(self):
        """更新后处理"""
        self.update_location_status()
    
    def on_trash(self):
        """删除前处理"""
        self.check_linked_transactions()
    
    def validate_unique_scrap_id(self):
        """验证余料编号唯一性"""
        if self.scrap_id:
            exists = frappe.db.exists("Scrap Material", {
                "scrap_id": self.scrap_id,
                "name": ["!=", self.name]
            })
            if exists:
                frappe.throw(f"余料编号 {self.scrap_id} 已存在，请使用其他编号")
    
    def validate_warehouse_location(self):
        """验证仓库和库位有效性"""
        if self.warehouse and self.location:
            # 检查库位是否属于指定仓库
            location_doc = frappe.get_doc("Scrap Location", self.location)
            if location_doc.warehouse != self.warehouse:
                frappe.throw(f"库位 {self.location} 不属于仓库 {self.warehouse}")
            
            # 检查仓库和库位状态
            warehouse_doc = frappe.get_doc("Scrap Warehouse", self.warehouse)
            if warehouse_doc.status != "启用":
                frappe.throw(f"仓库 {self.warehouse} 未启用，无法存放余料")
            
            if location_doc.status != "启用":
                frappe.throw(f"库位 {self.location} 未启用，无法存放余料")
    
    def validate_dimensions(self):
        """验证尺寸数据"""
        if flt(self.length) <= 0:
            frappe.throw("长度必须大于0")
        
        if flt(self.width) <= 0:
            frappe.throw("宽度必须大于0")
        
        if flt(self.thickness) <= 0:
            frappe.throw("厚度必须大于0")
    
    def validate_quantity(self):
        """验证数量"""
        if flt(self.quantity) <= 0:
            frappe.throw("数量必须大于0")
    
    def set_creation_date(self):
        """设置创建日期"""
        if not self.creation_date:
            self.creation_date = today()
    
    def generate_qr_code(self):
        """生成二维码"""
        if not self.qr_code:
            # 生成二维码内容，包含余料编号和基本信息
            qr_data = {
                "scrap_id": self.scrap_id,
                "material_type": self.material_type,
                "material_name": self.material_name,
                "color_pattern": self.color_pattern,
                "dimensions": f"{self.length}x{self.width}x{self.thickness}",
                "quantity": self.quantity,
                "unit": self.unit,
                "location": self.location,
                "warehouse": self.warehouse
            }
            self.qr_code = json.dumps(qr_data, ensure_ascii=False)
    
    def update_location_status(self):
        """更新库位状态"""
        if self.location:
            # 检查库位中的余料数量
            count = frappe.db.count("Scrap Material", {
                "location": self.location,
                "status": ["!=", "已报废"]
            })
            
            # 更新库位状态
            location_doc = frappe.get_doc("Scrap Location", self.location)
            if count > 0 and location_doc.status == "空闲":
                location_doc.status = "使用中"
                location_doc.save(ignore_permissions=True)
            elif count == 0 and location_doc.status == "使用中":
                location_doc.status = "空闲"
                location_doc.save(ignore_permissions=True)
    
    def check_linked_transactions(self):
        """检查关联的事务"""
        # 检查是否有关联的入库单
        receipt_count = frappe.db.count("Scrap Receipt", {
            "scrap_material": self.name,
            "docstatus": ["!=", 2]
        })
        
        # 检查是否有关联的出库单
        issue_count = frappe.db.count("Scrap Issue", {
            "scrap_material": self.name,
            "docstatus": ["!=", 2]
        })
        
        # 检查是否在待取清单中
        pickup_count = frappe.db.count("Scrap Pickup List", {
            "scrap_material": self.name,
            "docstatus": ["!=", 2]
        })
        
        if receipt_count > 0 or issue_count > 0 or pickup_count > 0:
            frappe.throw(f"余料 {self.scrap_id} 存在关联的事务记录，无法删除")
    
    def change_status(self, new_status):
        """更改余料状态"""
        if new_status not in ["可用", "已使用", "异常", "锁定", "待切割", "已切割", "待报废", "已报废"]:
            frappe.throw("无效的状态值")
        
        old_status = self.status
        self.status = new_status
        self.save(ignore_permissions=True)
        
        # 记录状态变更日志
        frappe.get_doc({
            "doctype": "Comment",
            "comment_type": "Info",
            "reference_doctype": self.doctype,
            "reference_name": self.name,
            "comment_email": frappe.session.user,
            "content": f"状态从 {old_status} 变更为 {new_status}"
        }).insert(ignore_permissions=True)
    
    @staticmethod
    def get_available_materials(warehouse=None, material_type=None):
        """获取可用余料列表"""
        filters = {"status": "可用"}
        
        if warehouse:
            filters["warehouse"] = warehouse
        
        if material_type:
            filters["material_type"] = material_type
        
        return frappe.get_all("Scrap Material", 
                            filters=filters,
                            fields=["name", "scrap_id", "warehouse", "location", 
                                   "material_type", "material_name", "color_pattern",
                                   "length", "width", "thickness", "quantity", "unit"],
                            order_by="creation_date desc")
    
    @staticmethod
    def get_material_by_id(scrap_id):
        """根据余料编号获取余料信息"""
        return frappe.get_doc("Scrap Material", {"scrap_id": scrap_id})
    
    @staticmethod
    def get_materials_by_location(location):
        """获取指定库位的余料"""
        return frappe.get_all("Scrap Material",
                            filters={"location": location},
                            fields=["name", "scrap_id", "material_type", "material_name",
                                   "color_pattern", "length", "width", "thickness",
                                   "quantity", "unit", "status"],
                            order_by="creation_date desc")